// N1Thread.cpp: implementation of the N1Thread class.
//
//////////////////////////////////////////////////////////////////////

#include "N1Thread.h"
#include "N1ThreadSingleton.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
N1ThreadSingleton<N1Thread*>  gThread = (void*)NULL;
N1UInt32 N1Thread::m_nCount = 1;

N1Thread::N1Thread() {
    m_nCount++;
}

N1Thread::~N1Thread() {
    m_nCount--;
}

N1Thread* N1Thread::currentThread() {
    return gThread;
}

N1UInt32  N1Thread::currentThreadId() {
    return GetCurrentThreadId();
}

const char* N1Thread::description() const {
    return "dfs";
}

//void N1Thread::detachNewThreadSelector() {
//}
typedef struct {
    N1Object *Selector;
    N1Object *Param;
} N1_THREAD_PARAM, *LPN1_THREAD_PARAM;

DWORD WINAPI ThreadProc(LPVOID lpParameter) {
    LPN1_THREAD_PARAM tp = (LPN1_THREAD_PARAM)lpParameter;

    gThread = new N1Thread;
    gThread->m_hThread = GetCurrentThread();
    gThread->m_nThreadId = GetCurrentThreadId();

    tp->Selector->onNewThread(tp->Param);

    delete gThread;
    delete tp;
    return 0;
}

void N1Thread::detachNewThreadSelector(N1Object *selector, N1Object *param) {
    LPN1_THREAD_PARAM tp = new N1_THREAD_PARAM;

    tp->Selector = selector;
    tp->Param    = param;

    DWORD  nThreadId = 0;
    HANDLE hThread = CreateThread(NULL, 
                                  16384,      // initial thread stack size
                                  ThreadProc, // pointer to thread function
                                  tp,        // argument for new thread
                                  0,          // creation flags
                                  &nThreadId   // pointer to receive thread ID
                                 );
}

BOOL N1Thread::isMultiThreaded() {
    return (m_nCount>1);
}

void N1Thread::exit() {
}

double N1Thread::threadPriority() {
    HANDLE hThread = currentThread()->m_hThread;
    int priority = GetThreadPriority(hThread);
    switch(priority) {
        case THREAD_PRIORITY_IDLE:
            return 0.1;
        case THREAD_PRIORITY_LOWEST:
            return 0.3;
        case THREAD_PRIORITY_BELOW_NORMAL:
            return 0.4;
        case THREAD_PRIORITY_NORMAL:
            return 0.5;
        case THREAD_PRIORITY_ABOVE_NORMAL:
            return 0.6;
        case THREAD_PRIORITY_HIGHEST:
            return 0.9;
        case THREAD_PRIORITY_TIME_CRITICAL:
            return 1;
        default:
            return 0;
    }
    return 0;
}

BOOL N1Thread::setThreadPriority(double priority) {
    int nPriority;
    if(priority<=0.1)
        nPriority = THREAD_PRIORITY_IDLE;
    else if(priority<=0.4)
        nPriority = THREAD_PRIORITY_LOWEST;
    else if(priority<=0.6)
        nPriority = THREAD_PRIORITY_NORMAL;
    else if(priority<=0.7)
        nPriority = THREAD_PRIORITY_ABOVE_NORMAL;
    else if(priority<=0.9)
        nPriority = THREAD_PRIORITY_HIGHEST;
    else if(priority>0.9)
        nPriority = THREAD_PRIORITY_TIME_CRITICAL;
    HANDLE hThread = currentThread()->m_hThread;
    return SetThreadPriority(hThread, nPriority);
}

